Skip to content

Experiment: Reborrow traits#151753

Open
aapoalas wants to merge 4 commits intorust-lang:mainfrom
aapoalas:aapoalas/reborrow-and-coerce-shared-first-version
Open

Experiment: Reborrow traits#151753
aapoalas wants to merge 4 commits intorust-lang:mainfrom
aapoalas:aapoalas/reborrow-and-coerce-shared-first-version

Conversation

@aapoalas
Copy link
Contributor

@aapoalas aapoalas commented Jan 27, 2026

View all comments

With this PR we now have basic functional Reborrow and CoerceShared traits. The current limitations are:

  1. Reborrowable types can only have one lifetime parameter, so as to avoid having to figure out and store in rmeta the information of which lifetimes weaken during reborrowing.
  2. Reborrowing of &mut wrappers is working (though I've not tested generic wrappers like Option<&mut T> yet), but CoerceShared of &mut wrappers currently causes an ICE.

The remaining tasks to complete before I'd consider this PR mergeable are:

  • Fix ICE on CoerceShared. Unfortunately this might require dipping into rmeta.
  • Expand the tests to give a more complete view of the current state of the experiment.

Reborrow traits experiment: #145612

Co-authored by @dingxiangfei2009

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Jan 27, 2026
@rust-log-analyzer

This comment has been minimized.

@aapoalas aapoalas force-pushed the aapoalas/reborrow-and-coerce-shared-first-version branch from e4c08f7 to 3b1957a Compare January 27, 2026 17:03
@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-bors

This comment has been minimized.

@aapoalas aapoalas marked this pull request as ready for review February 2, 2026 21:16
@rustbot
Copy link
Collaborator

rustbot commented Feb 2, 2026

Some changes occurred in rustc_ty_utils::consts.rs

cc @BoxyUwU

Some changes occurred in match checking

cc @Nadrieril

This PR changes MIR

cc @oli-obk, @RalfJung, @JakobDegen, @vakaras

This PR changes rustc_public

cc @oli-obk, @celinval, @ouz-a, @makai410

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred to constck

cc @fee1-dead

Some changes occurred to the CTFE / Miri interpreter

cc @rust-lang/miri

Some changes occurred in compiler/rustc_codegen_cranelift

cc @bjorn3

Some changes occurred to the CTFE machinery

cc @RalfJung, @oli-obk, @lcnr

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 2, 2026
@aapoalas
Copy link
Contributor Author

aapoalas commented Feb 2, 2026

r? compiler

@rustbot rustbot assigned jackh726 and unassigned tmandry Feb 2, 2026
}

adjustment::Adjust::GenericReborrow(_reborrow) => {
// Do the magic!
Copy link
Contributor

@dingxiangfei2009 dingxiangfei2009 Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh we should call delegates. See the ReborrowPin arm and that is basically what we want to do.

And eventually we should be able to subsume ReborrowPin case hopefully.

// `&mut T: DerefMut` tho, so it's kinda moot.
}
Adjust::GenericReborrow(_) => {
// No effects to enforce here.
Copy link
Contributor

@dingxiangfei2009 dingxiangfei2009 Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do something here. The type would change after a generic reborrow, ie the CoerceShared case.

@BoxyUwU
Copy link
Member

BoxyUwU commented Feb 3, 2026

Where can I read context on what CoerceShared is/why it exists, and what the design for reborrow traits is

@aapoalas
Copy link
Contributor Author

aapoalas commented Feb 3, 2026

Where can I read context on what CoerceShared is/why it exists, and what the design for reborrow traits is

I added a link to the experiment tracking issue but put it very shortly: Reborrow is to struct X<'a>(..) what &mut *x is for &mut T, and CoerceShared is the equivalent operation as &*x. CoerceShared takes a type argument instead of having an associated type in expectation of it being possible to reborrow types like struct Double(&mut A, &mut B) which would then have three different "shared reference" variants: struct DR1(&A, &mut B), struct DR2(&mut A, &B), and struct DR3(&A, &B), though I am currently doubting the wisdom of this choice and it may return to using an associated type.

@BoxyUwU
Copy link
Member

BoxyUwU commented Feb 3, 2026

I think I'll just
r? me
on this since I know jack is quite busy with coercions work right now and this should probably have a types reviewer 🤔

@rustbot rustbot assigned BoxyUwU and unassigned jackh726 Feb 3, 2026
@aapoalas
Copy link
Contributor Author

aapoalas commented Feb 3, 2026

I think I'll just r? me on this since I know jack is quite busy with coercions work right now and this should probably have a types reviewer 🤔

Thank you <3 my top secret plan (designed together with tmandry) was to get a compiler review and then reroll into types to that view as well so that works well :)

@jackh726
Copy link
Member

jackh726 commented Feb 3, 2026

I think I'll just r? me on this since I know jack is quite busy with coercions work right now and this should probably have a types reviewer 🤔

Appreciated.

Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this would be better, but if there are also plans to generalize field projections later, it would probably be good to try to keep references and custom ref types in sync

View changes since this review

@BoxyUwU
Copy link
Member

BoxyUwU commented Feb 14, 2026

given oli has more context on this,
r? oli-obk

(though if you can't review this we should chat about it and figure out what to do here :>)

@rustbot rustbot assigned oli-obk and unassigned BoxyUwU Feb 14, 2026
@rustbot
Copy link
Collaborator

rustbot commented Feb 14, 2026

oli-obk is not on the review rotation at the moment.
They may take a while to respond.

WrapUnsafeBinder(Operand<'tcx>, Ty<'tcx>),

/// Creates a bitwise copy of the indicated place with the same type (if Mut) or its
/// CoerceShared target type (if Not), and disables the place for writes (and reads, if Mut) for
Copy link
Member

@RalfJung RalfJung Feb 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does "disables the place" mean?
The first half sounds like a description of the operational semantics, but the second half sounds like a description of what happens in the borrow checker. It's quite confusing to mix those together.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same thing as what b does for a here:

let a = &mut 0u32;
let b = &mut *a;

a is "disabled" for reads and writes while b lives. So this is borrow checker stuff indeed; I assumed that'd be relevant information here. And I must admit I assumed it is fundamentally an opsem consideration; is &mut XOR & not part of opsem?

If I split this up, what sort of split would you expect? Would the first half explain simply that for a btiwse copy is produced (and that in the future Not reborrows may include reordering and dropping of fields), and then the second half explain that the borrow checker creates a covariant lifetime relation between the source and target's only lifetime (and that in the future multiple lifetimes may participate in the reborrowing, in which case all source lifetimes are covariantly related to their corresponding pair on the target)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is relevant but it is not opsem. You implemented the opsem in this PR when you added support in interpret and you didn't do anything wrt disabling the source there did you? :)

You can just have two paragraphs, one for what it means for the borrow checker and one for what it means operationally.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this is still unresolved, so the PR is not fully ready yet)

Copy link
Contributor Author

@aapoalas aapoalas Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, mildly forgot. Fixed now.

Let me know if this is not still up to snuff in your view! <3

Copy link
Contributor

@oli-obk oli-obk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stuck somewhere in the middle of a review, but submitting at this point as I gotta run

I have come back to "this should just be a BorrowKind::Custom", which I don't think will affect perf or complexity (and def not more than this PR does), but I can finish reviewing if you want before doing such a major refactor of the PR

View changes since this review

self.sub_types(rv_ty, place_ty, location.to_locations(), category)
// Note: we've checked Reborrow/CoerceShared type matches
// separately in fn visit_assign.
if !matches!(rv, Rvalue::Reborrow(_, _))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should not have a visit_assign in this visitor, but instead do an if/else chain here to handle the generic reborrow case

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't do this just yet.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I'm not sure if we can do this: visit_assign is called in eg. call(a) for a whereas visit_statement I presume would only be called let b = a;

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 24, 2026
@rustbot
Copy link
Collaborator

rustbot commented Feb 24, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@aapoalas
Copy link
Contributor Author

Stuck somewhere in the middle of a review, but submitting at this point as I gotta run

I have come back to "this should just be a BorrowKind::Custom", which I don't think will affect perf or complexity (and def not more than this PR does), but I can finish reviewing if you want before doing such a major refactor of the PR

View changes since this review

I would very much appreciate that: I'm very afraid of doing such a major rewrite of the entire of the feature. This isn't exactly a great reason, but from a personal point of view it is quite discouraging to have something working after months of work and then hear that nah, this'd actually better be done an entire different way :D in that sense I would personally prefer landing this and then starting on the rewrite while concurrently gathering feedback from users.

@aapoalas
Copy link
Contributor Author

aapoalas commented Feb 26, 2026

I have come back to "this should just be a BorrowKind::Custom", which I don't think will affect perf or complexity (and def not more than this PR does), but I can finish reviewing if you want before doing such a major refactor of the PR

We discussed this a little: mir/syntax.rs BorrowKind::Custom kind of seems make sense, but it does leak into a lot of places (like BorrowData in borrow_set.rs) and it might not make sense in all of these places... maybe?

The main question we had was: what was your thinking about usage of the BorrowKind? We'd presumably put use it in ExprKind::Borrow to make generic reborrow part of that family of expressions, but do we then take the logical route and use Rvalue::Ref as well? Therein things really start to make ... maybe less sense? The first payload of Rvalue::Ref is the lifetime '_ in &'_ T, but for Rvalue::Ref(_, BorrowKind::Custom, _) we would never use that lifetime because the correct lifetime to use is coming in the type.

EDIT:

We currently pass the T through ExprKind::Reborrow – if using ExprKind::Borrow we'd presumably have to recover the T through either the source ExprId or through the assignment. We'll try out removing the T type pass-through from ExprKind::Reborrow though, and see if it turns out to be possible to recover it through other means or if it really is necessary.

Turns out we weren't even using the T that we passed through, so that part was definitely unnecessary worries. The lifetime/region in Rvalue::Ref being unused is a thing we would still have.

@rustbot

This comment has been minimized.

@aapoalas aapoalas force-pushed the aapoalas/reborrow-and-coerce-shared-first-version branch from 3b3699f to c10c973 Compare February 26, 2026 21:52
@rustbot

This comment has been minimized.

@aapoalas
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Feb 26, 2026
@rust-bors

This comment has been minimized.

@aapoalas aapoalas force-pushed the aapoalas/reborrow-and-coerce-shared-first-version branch from a739e9d to b9d634a Compare February 28, 2026 20:15
@rustbot
Copy link
Collaborator

rustbot commented Feb 28, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rust-log-analyzer
Copy link
Collaborator

The job pr-check-2 failed! Check out the build log: (web) (plain enhanced) (plain)

Click to see the possible cause of the failure (guessed by this bot)
/dev/sda15      105M  6.2M   99M   6% /boot/efi
tmpfs           1.6G   12K  1.6G   1% /run/user/1001
================================================================================

Sufficient disk space available (95787412KB >= 52428800KB). Skipping cleanup.
##[group]Run echo "[CI_PR_NUMBER=$num]"
echo "[CI_PR_NUMBER=$num]"
shell: /usr/bin/bash --noprofile --norc -e -o pipefail {0}
---
    Checking rustc_codegen_cranelift v0.1.0 (/checkout/compiler/rustc_codegen_cranelift)
error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has 3 fields
    --> compiler/rustc_codegen_cranelift/src/base.rs:632:34
     |
 632 |                 Rvalue::Reborrow(_, place) => {
     |                                  ^  ^^^^^ expected 3 fields, found 2
     |
    ::: compiler/rustc_middle/src/mir/syntax.rs:1493:14
     |
1493 |     Reborrow(Mutability, Place<'tcx>, Ty<'tcx>),
     |              ----------  -----------  -------- tuple variant has 3 fields
     |
help: use `_` to explicitly ignore each field
     |
 632 |                 Rvalue::Reborrow(_, place, _) => {
     |                                          +++

For more information about this error, try `rustc --explain E0023`.
[RUSTC-TIMING] rustc_codegen_cranelift test:false 0.961
error: could not compile `rustc_codegen_cranelift` (lib) due to 1 previous error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-clippy Relevant to the Clippy team. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-libs Relevant to the library team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants